/*
    Copyright 2009 Mario Ivankovits

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */
import com.avaje.ebean.Ebean;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.Transaction;
import com.avaje.ebean.server.lib.GlobalProperties;
import com.avaje.ebean.server.lib.sql.DataSourceGlobalManager;
import com.avaje.ebean.server.lib.sql.DataSourcePool;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

public class RepeatableRead
{
    public static void main(String[] args) throws SQLException
    {
        createDatabase();

        EbeanServer server = Ebean.getServer(null);

        populateDatabase(server);

        // read entity without transaction ... this automatically creates one just for this very statement
        TestEntity readEntity1 = server.find(TestEntity.class, 1L);
        readEntity1.getField1(); // read content of field1

        // and again. We now read the same database row but got two independent instances
        TestEntity readEntity2 = server.find(TestEntity.class, 1L);
        readEntity2.getField2(); // read content of field2

        System.err.println(
                String.format("instanceof first entity 0x%06x - instanceof second entity 0x%06x",
                        System.identityHashCode(readEntity1),
                        System.identityHashCode(readEntity2)));

        if (readEntity1 == readEntity2)
        {
            throw new IllegalStateException("should not be of same instance");
        }

        // now lets start a transaction
        Transaction tx = server.beginTransaction();
        TestEntity readEntity1_1 = server.find(TestEntity.class, 1L);
        readEntity1_1.getField2();

        TestEntity readEntity2_1 = server.find(TestEntity.class, 1L);
        readEntity2_1.getField1();

        // we now got the same instance for the same row  

        System.err.println(
                String.format("instanceof first entity 0x%06x - instanceof second entity 0x%06x",
                        System.identityHashCode(readEntity1_1),
                        System.identityHashCode(readEntity2_1)));

        tx.commit();

        if (readEntity1_1 != readEntity2_1)
        {
            throw new IllegalStateException("should be of same instance");
        }
    }

    private static void populateDatabase(EbeanServer server)
    {
        Transaction tx = server.beginTransaction();

        TestEntity e1 = new TestEntity();
        e1.setId(1L);
        e1.setField1("e1f1");
        e1.setField2("e1f2");
        server.save(e1);

        tx.commit();
    }

    private static void createDatabase()
            throws SQLException
    {
        DataSourcePool dsp = DataSourceGlobalManager.getDataSource(null, GlobalProperties.getConfigProperties());
        Connection conn = dsp.getConnection();
        Statement stm = conn.createStatement();
        stm.execute("create table test_entity ( id integer, field_1 varchar(80), field_2 varchar(80), version integer, constraint pk primary key(id))");
        stm.close();
        conn.commit();
        conn.close();
    }
}
